package com.jzz;

import com.jzz.algorithm.AesAlgorithm;
import com.jzz.algorithm.DesAlgorithm;
import com.jzz.algorithm.RsaAlgorithm;
import com.jzz.exec.CipherExecutor;

import java.io.File;

public class SCli {

    public static void main(String[] args) {
        if (args.length == 0) {
            usage();
        } else {
            generateOptions(args);
        }
    }

    private static Options generateOptions(String[] args) {
        Options options = new Options();
        String neededArgs = "-a-d-e-K-k";

        int i = 0;
        while (i < args.length) {
            switch (args[i]) {
                case "-a":
                    if (i == args.length - 1) {
                        error("No argument value for \"-a\"");
                        return null;
                    }
                    String a = args[i + 1].toLowerCase();
                    if ("des".equals(a)) {
                        options.setAlgorithm(new DesAlgorithm());
                    } else if ("aes".equals(a)) {
                        options.setAlgorithm(new AesAlgorithm());
                    } else if ("rsa".equals(a)) {
                        options.setAlgorithm(new RsaAlgorithm());
                    } else {
                        invalidArg(a);
                    }
                    i += 2;
                    neededArgs = neededArgs.replace("-a", "");
                    break;
                case "-b":
                    options.setInputB64(true);
                    i++;
                    break;
                case "-B":
                    options.setOutputB64(true);
                    i++;
                    break;
                case "-d":
                    options.setDecryption(true);
                    i++;
                    neededArgs = neededArgs.replace("-d-e", "");
                    break;
                case "-e":
                    options.setDecryption(false);
                    i++;
                    neededArgs = neededArgs.replace("-d-e", "");
                    break;
                case "-h":
                    usage();
                    return null;
                case "-K":
                    if (i == args.length - 1) {
                        error("No argument value for \"-K\"");
                        return null;
                    }
                    String f = args[i + 1];
                    if (!new File(f).exists()) {
                        error("File " + f + " not exists.");
                        return null;
                    } else {
                        options.setKeyFile(new File(f));
                    }

                    i += 2;
                    neededArgs = neededArgs.replace("-K-k", "");
                    break;
                case "-k":
                    if (i == args.length - 1) {
                        error("No argument value for \"-k\"");
                        return null;
                    }
                    String k = args[i + 1];
                    options.setKey(k.getBytes());

                    i += 2;
                    neededArgs = neededArgs.replace("-K-k", "");
                    break;
                case "-o":
                    if (i == args.length - 1) {
                        error("No argument value for \"-o\"");
                        return null;
                    }
                    String o = args[i + 1];
                    options.setOutFile(new File(o));

                    i += 2;
                    break;
                case "-i":
                    if (i == args.length - 1) {
                        error("No argument value for \"-i\"");
                        return null;
                    }
                    String i1 = args[i + 1];
                    options.setInFile(new File(i1));

                    i += 2;
                    break;
                default:
                    if (i == args.length - 1) {
                        options.setData(args[i].getBytes());
                    } else {
                        invalidArg(args[i]);
                    }
                    i++;
                    break;
            }
        }

        if (neededArgs.isEmpty()) {
            options.setExecutor(new CipherExecutor(options));
            return options;
        } else {
            error("Missing arguments" + neededArgs.replaceAll("-", " -"));
            return null;
        }
    }

    private static void usage() {
        System.out.println("usage: java SCli <-a algorithm> [-b] [-B] <[-d] | [-e]> [-h]");
        System.out.println("                 <[-K key_file] | [-k key]>");
        System.out.println("                 [-o output_file] [[-i input_file] | data]");
        System.out.println("options:");

        System.out.println("\t-a algorithm\t\t\t选择加密算法。\n\t\t\t\t\t可选[aes | des | rsa]");
        System.out.println("\t-b\t\t\t\t输入采用Base64编码。");
        System.out.println("\t-B\t\t\t\t输出采用Base64编码。");
        System.out.println("\t-d\t\t\t\t解密。");
        System.out.println("\t-e\t\t\t\t加密。");
        System.out.println("\t-h\t\t\t\t列出该帮助信息。");

        System.out.println("\t-K key_file\t\t\t选择密钥文件。");
        System.out.println("\t\t\t\t\t非对称加密算法使用公钥加密，私钥解密。");
        System.out.println("\t\t\t\t\t对称加密算法为密钥。");

        System.out.println("\t-k key\t\t\t\t指定密钥。");
        System.out.println("\t\t\t\t\t非对称加密算法使用公钥加密，私钥解密。");
        System.out.println("\t\t\t\t\t对称加密算法为密钥。");

        System.out.println("\t-o output_file\t\t\t指定输出文件。");

        System.out.println("\t-i input_file\t\t\t指定输入文件。");

        System.out.println("\nexample:");
        System.out.println("\tEncrypt \"mymessage\" using DES algorithm with key \"mydeskey\":");
        System.out.println("\t\tjava SCli -e -a des -k mydeskey mymessage");
    }

    private static void invalidArg(String arg) {
        System.out.println("Invalid argument: " + arg + ". Use \"java SCli -h\" to see the usage.");
        System.exit(0);
    }

    private static void error(String msg) {
        System.out.println("Error: " + msg);
        System.exit(0);
    }
}
